package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.dubbo.api.db.QuestionApi;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.dubbo.api.db.UserInfoApi;
import com.tanhua.dubbo.api.mongo.RecommendUserApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.dubbo.api.mongo.UserLocationApi;
import com.tanhua.dubbo.api.mongo.VisitorApi;
import com.tanhua.model.db.Question;
import com.tanhua.model.db.User;
import com.tanhua.model.db.UserInfo;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.UserLike;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.*;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class TanhuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;
    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private QuestionApi questionApi;
    @DubboReference
    private UserLocationApi userLocationApi;
    @DubboReference
    private UserApi userApi;
    @DubboReference
    private UserLikeApi userLikeApi;
    @DubboReference
    private VisitorApi visitorApi;

    @Autowired
    private HuanXinTemplate huanXinTemplate;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${tanhua.default.recommend.users}")
    private String recommendUserIds;

    /**
     * 今日最佳
     * @return
     */
    public TodayBestVo todayBest() {
        Long loginUserId = UserHolder.getUserId();
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(loginUserId);
        //如果没有佳人 则给个客服 1-99
        if (null == recommendUser) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(loginUserId%99 + 1);
            recommendUser.setScore(95d);
        }
        UserInfo userInfo = userInfoApi.getById(recommendUser.getUserId());
        return TodayBestVo.init(userInfo, recommendUser);
    }

    /**
     * 推荐朋友
     * @param recommendUserVo
     * @return
     */
    public PageResult<TodayBestVo> recommendation(RecommendUserVo recommendUserVo) {
        Long page = recommendUserVo.getPage();
        Long pagesize = recommendUserVo.getPagesize();
        List<TodayBestVo> voList = new ArrayList<>();
        PageResult<RecommendUser> pageResult = recommendUserApi.recommendation(page, pagesize, UserHolder.getUserId());
        List<RecommendUser> recommendUsers = pageResult.getItems();
        //若没有推荐好友，则推荐10个客服人员
        if(CollectionUtils.isEmpty(recommendUsers) && recommendUserVo.getPage() == 1) {
            recommendUsers = getDefaultRecommendUsers(pagesize);
            pageResult.setCounts(pagesize);
            pageResult.setPage(1L);
            pageResult.setPages(1L);
        }

        List<Long> ids = recommendUsers.stream().map(RecommendUser::getUserId)
                .collect(Collectors.toList());
        UserInfo userInfoCondition = new UserInfo();
        //BeanUtils.copyProperties(recommendUserVo, userInfoCondition);
        userInfoCondition.setAge(recommendUserVo.getAge());
        userInfoCondition.setGender(recommendUserVo.getGender());
        Map<Long, UserInfo> userInfoMap =  userInfoApi.getBatchIdsByCondition(ids, userInfoCondition);

        for (RecommendUser recommendUser : recommendUsers) {
            UserInfo userInfo = userInfoMap.get(recommendUser.getUserId());
            if(null != userInfo)
                voList.add(TodayBestVo.init(userInfo, recommendUser));
        }

        return new PageResult<>(page, pagesize, pageResult.getCounts(), voList);
    }

    /**
     * 默认推荐好友
     * @return
     */
    private List<RecommendUser> getDefaultRecommendUsers(Long pagesize) {
        List<RecommendUser> list = new ArrayList<>();
        int startIndex = RandomUtils.nextInt(1,90);
        RecommendUser recommendUser = null;
        for (long i = startIndex; i < startIndex + pagesize; i++) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(i);
            recommendUser.setScore(RandomUtils.nextDouble(80,100));
            list.add(recommendUser);
        }
        return list;
    }

    /**
     * 查看佳人信息
     * @param userId
     * @return
     */
    public TodayBestVo personalInfo(Long userId) {
        UserInfo userInfo = userInfoApi.getById(userId);
        RecommendUser recommendUser = recommendUserApi.getByUserId(userId, UserHolder.getUserId());
        if (null == recommendUser) {
            recommendUser = new RecommendUser();
            recommendUser.setScore(Double.valueOf(85 + userId % 15));
        }
        //保存访客记录
        Visitors visitors = new Visitors();
        visitors.setUserId(userId);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom(Constants.VISITOR_FROM);
        visitors.setScore(recommendUser.getScore());

        visitorApi.save(visitors);

        return TodayBestVo.init(userInfo, recommendUser);
    }

    /**
     * 查询问题
     * @param userId
     * @return
     */
    public String queryQuestions(Long userId) {
        Question question = questionApi.findByUserId(userId);
        return null != question ? question.getTxt() : Constants.DEFAULT_QUESTION;
    }

    /**
     * 回复问题
     * @param params
     */
    public void replyStrangerQuestions(Map<String,String> params) {
        Long userId  = Long.valueOf(params.get("userId"));
        //佳人环信账号
        User user = userApi.find(new User(userId));
        User loginUser = UserHolder.getUser();
        UserInfo loginUserInfo = userInfoApi.getById(loginUser.getId());
        Map<String, Object> map = new HashMap<>();
        map.put("userId", loginUser.getId());
        map.put("huanXinId", loginUser.getHxUser());
        map.put("nickname", loginUserInfo.getNickname());
        map.put("strangerQuestion", queryQuestions(userId));
        map.put("reply", params.get("reply"));

        if (!huanXinTemplate.sendMsg(user.getHxUser(), JSON.toJSONString(map))) {
            throw new TanHuaException(ErrorResult.error());
        }
    }

    /**
     * 左滑右滑
     * @return
     */
    public List<TodayBestVo> cards() {
        List<RecommendUser> recommendUsers = recommendUserApi.findCards(UserHolder.getUserId(), 10);
        //若不存在 则使用客服数据
        if(CollectionUtils.isEmpty(recommendUsers)) {
            recommendUsers = new ArrayList<>();
            String[] userIds  = recommendUserIds.split(",");
            for (String userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Long.valueOf(userId));
                recommendUser.setScore(RandomUtils.nextDouble(80,90));
                recommendUsers.add(recommendUser);
            }
        }

        List<Long> ids = recommendUsers.stream().map(RecommendUser::getUserId)
                        .collect(Collectors.toList());
        Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(ids, null);
        List<TodayBestVo> todayBestVos = new ArrayList<>();
        recommendUsers.forEach(recommendUser -> {
            UserInfo userInfo = userInfoMap.get(recommendUser.getUserId());
            if(null != userInfo)
                todayBestVos.add(TodayBestVo.init(userInfo,recommendUser));
        });

        return todayBestVos;
    }

    /**
     * 左滑右滑
     * @param userId
     * @param isLike
     */
    public void love(Long userId, boolean isLike) {
        UserLike userLike = new UserLike();
        userLike.setUserId(UserHolder.getUserId());
        userLike.setLikeUserId(userId);
        userLike.setIsLike(isLike);

        boolean isFriend = userLikeApi.save(userLike);
        String likeKey = Constants.USER_LIKE_KEY + UserHolder.getUserId();
        String unLikeKey = Constants.USER_NOT_LIKE_KEY + UserHolder.getUserId();

        if(isLike) {
            redisTemplate.opsForSet().add(likeKey, userId.toString());
            redisTemplate.opsForSet().remove(unLikeKey, userId.toString());
        }else {
            redisTemplate.opsForSet().add(unLikeKey, userId.toString());
            redisTemplate.opsForSet().remove(likeKey, userId.toString());
        }

        if(isFriend) {
            huanXinTemplate.addContact(Constants.HX_USER_PREFIX + userId, Constants.HX_USER_PREFIX + UserHolder.getUserId());
        }
    }

    /**
     * 搜附近
     * @param gender
     * @param distance
     * @return
     */
    public List<NearUserVo> searchNearBy(String gender, Long distance) {
        List<Long> userIds = userLocationApi.searchNearBy(UserHolder.getUserId(), distance);
        List<NearUserVo> result = new ArrayList<>();

        if(CollectionUtils.isNotEmpty(userIds)) {
            UserInfo condition = new UserInfo();
            condition.setGender(gender);
            Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(userIds, condition);

            result = userInfoMap.values().stream().map(u -> NearUserVo.init(u))
                    .collect(Collectors.toList());
        }

        return result;
    }

    /**
     * 根据类型查找用户
     *
     * @param page
     * @param pageSize
     * @param nickname
     * @param type
     * @return
     */
    public PageResult findFriendsByType(Long page, Long pageSize, String nickname, Integer type) {

        switch (type){
            //相互喜欢
            case 1:{
                //相互喜欢则为好友，所以可以直接查好友表
                //这里不用这个方法
                PageResult<UserLike> pageResult = userLikeApi.findLikeByUserId(UserHolder.getUserId(), page, pageSize);
                List<UserLike> userLikes = pageResult.getItems();
                if(CollectionUtils.isEmpty(userLikes)) {
                    return new PageResult(page, pageSize, pageResult.getCounts(), null);
                }

                List<Long> likeUserIds = userLikes.stream().map(UserLike::getLikeUserId).collect(Collectors.toList());
                List<Long> eachLikeUserIds = new ArrayList<>();
                for (Long userId : likeUserIds) {
                    if(userLikeApi.isLike(userId, UserHolder.getUserId())){
                        eachLikeUserIds.add(userId);
                    }
                }

                List<UserInfoVoAge> result = getList(nickname, userLikes, eachLikeUserIds, 1);

                return new PageResult(page, pageSize, pageResult.getCounts(), result);
            }
            //喜欢
            case 2:{
                PageResult<UserLike> pageResult = userLikeApi.findLikeByUserId(UserHolder.getUserId(), page, pageSize);
                List<UserLike> userLikes = pageResult.getItems();
                if(CollectionUtils.isEmpty(userLikes)) {
                    return new PageResult(page, pageSize, pageResult.getCounts(), null);
                }

                List<Long> userIds = userLikes.stream().map(UserLike::getLikeUserId).collect(Collectors.toList());
                List result = getList(nickname, userLikes, userIds, 2);

                return new PageResult(page, pageSize, pageResult.getCounts(), result);
            }
            //粉丝
            case 3:{
                Long userId = UserHolder.getUserId();
                PageResult<UserLike> pageResult = userLikeApi.findFansByLikeUserId(userId, page, pageSize);
                List<UserLike> userLikes = pageResult.getItems();
                if(CollectionUtils.isEmpty(userLikes)) {
                    return new PageResult(page, pageSize, pageResult.getCounts(), null);
                }
                List<Long> likeUserIds = userLikes.stream().map(UserLike::getUserId).collect(Collectors.toList());
                List<Long> userLikeIds= userLikeApi.findIsLikeUser(userId, likeUserIds);

                List<UserInfoVoAge> userInfos = getList(nickname, userLikes, userLikeIds, 3);
                return new PageResult(page, pageSize, pageResult.getCounts(), userInfos);
            }
            //谁看过我
            case 4:{
                PageResult<Visitors> pageResult = visitorApi.findVisitorsByPage(UserHolder.getUserId(), page, pageSize);
                List<Visitors> visitors = pageResult.getItems();
                if(CollectionUtils.isEmpty(visitors))
                    return new PageResult(page, pageSize, pageResult.getCounts(), null);

                List<Long> userIds = visitors.stream().map(Visitors::getVisitorUserId).collect(Collectors.toList());
                UserInfo condition = new UserInfo();
                condition.setNickname(nickname);
                Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(userIds, condition);

                List<UserInfoVoAge> vos = new ArrayList<>();
                visitors.forEach(v -> {
                    UserInfo userInfo = userInfoMap.get(v.getVisitorUserId());
                    if(null != userInfo) {
                        UserInfoVoAge userInfoVoAge = new UserInfoVoAge();
                        BeanUtils.copyProperties(userInfo, userInfoVoAge);
                        userInfoVoAge.setMatchRate(v.getScore().intValue());
                        vos.add(userInfoVoAge);
                    }
                });

                return new PageResult(page, pageSize, pageResult.getCounts(), vos);
            }
        }
        return null;
    }

    private List<UserInfoVoAge> getList(String nickname, List<UserLike> userLikes, List<Long> eachLikeUserIds, Integer type) {
        UserInfo condition = new UserInfo();
        condition.setNickname(nickname);
        List<UserInfoVoAge> result = new ArrayList();

        if(type == 3) {
            List<Long> ids = userLikes.stream().map(UserLike::getUserId).collect(Collectors.toList());
            Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(ids, condition);
            for (UserLike userLike : userLikes) {
                UserInfo userInfo = userInfoMap.get(userLike.getUserId());
                if(userInfo != null) {
                    UserInfoVoAge userInfoVoAge = new UserInfoVoAge();
                    BeanUtils.copyProperties(userInfo, userInfoVoAge);
                    if(eachLikeUserIds.contains(userInfo.getId())) {
                        userInfoVoAge.setAlreadyLove(true);
                    }else{
                        userInfoVoAge.setAlreadyLove(false);
                    }

                    result.add(userInfoVoAge);
                }
            }
            return result;
        }

        List<Long> ids = userLikes.stream().map(UserLike::getLikeUserId).collect(Collectors.toList());
        Map<Long, UserInfo> userInfoMap = userInfoApi.getBatchIdsByCondition(ids, condition);
        if(type == 2) {
            for (UserLike userLike : userLikes) {

                UserInfo userInfo = userInfoMap.get(userLike.getLikeUserId());
                if(userInfo != null) {
                    UserInfoVoAge userInfoVoAge = new UserInfoVoAge();
                    BeanUtils.copyProperties(userInfo, userInfoVoAge);
                    userInfoVoAge.setAlreadyLove(true);
                    if(eachLikeUserIds.contains(userInfo.getId())) {
                        userInfoVoAge.setAlreadyLove(true);
                    }else{
                        userInfoVoAge.setAlreadyLove(false);
                    }
                    result.add(userInfoVoAge);
                }
            }
            return result;
        }

        for (UserLike userLike : userLikes) {
            Long likeUserId = userLike.getLikeUserId();
            if(eachLikeUserIds.contains(likeUserId)) {
                UserInfo userInfo = userInfoMap.get(likeUserId);
                if(userInfo != null) {
                    UserInfoVoAge userInfoVoAge = new UserInfoVoAge();
                    BeanUtils.copyProperties(userInfo, userInfoVoAge);
                    userInfoVoAge.setAlreadyLove(true);
                    if(eachLikeUserIds.contains(userInfo.getId())) {
                        userInfoVoAge.setAlreadyLove(true);
                    }else{
                        userInfoVoAge.setAlreadyLove(false);
                    }
                    result.add(userInfoVoAge);
                }
            }
        }
        return result;
    }


    /**
     * 获取互相喜欢、关注、粉丝数量
     * @return
     */
    public CountsVo getCounts() {
        Long userId = UserHolder.getUserId();
        Integer eachLoveCount = userLikeApi.findEachLoveCount(userId);
        Integer loveCount = userLikeApi.findLoveCount(userId);
        Integer fanCount = userLikeApi.findFansCount(userId);

        CountsVo countsVo = new CountsVo(eachLoveCount, loveCount, fanCount);
        return countsVo;
    }

    /**
     * 是否喜欢
     * @param uid
     * @return
     */
    public Boolean alreadyLove(Long uid) {
        boolean isLike = userLikeApi.isLike(UserHolder.getUserId(), uid);
        return isLike;
    }

    /**
     * 取消喜欢
     * @param likeUserId
     */
    public void deleteLike(Long likeUserId) {
        Long userId = UserHolder.getUserId();
        userLikeApi.update(userId,likeUserId,false);
    }

    /**
     * 粉丝喜欢
     * @param likeUserId
     */
    public void fansLike(Long likeUserId) {
        Long userId = UserHolder.getUserId();
        UserLike userLike = new UserLike();
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setIsLike(true);
        userLikeApi.save(userLike);
    }
}
